package com.yvon.boot.mybatis.page;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.TypeDescriptor;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.data.domain.Page;

/**
 * 分页实体
 *
 * @author : Yvon
 * @since : 2021-09-03
 */
@ApiModel("分页数据列表")
@Data
public class ListData<T> {

    /**
     * 页码
     */
    @ApiModelProperty(value = "页码")
    private long page;

    /**
     * 页面大小
     */
    @ApiModelProperty(value = "页面大小")
    private long size;

    /**
     * 总页数
     */
    @ApiModelProperty(value = "总页数")
    private long totalPages;

    /**
     * 总数量
     */
    @ApiModelProperty(value = "总数量")
    private long totalElements;

    /**
     * 是否有上一页
     */
    @ApiModelProperty(value = "是否有上一页")
    private Boolean hasPrevious;

    /**
     * 是否有下一页
     */
    @ApiModelProperty(value = "是否有下一页")
    private Boolean hasNext;

    /**
     * 是否是第一页
     */
    @ApiModelProperty(value = "是否是第一页")
    private Boolean first;

    /**
     * 是否是最后一页
     */
    @ApiModelProperty(value = "是否是最后一页")
    private Boolean last;

    /**
     * 分页列表
     */
    @ApiModelProperty(value = "分页列表")
    private List<T> list;

    /**
     * 扩展字段
     */
    private Map<String, ?> extension;

    /**
     * 包装SpringData分页参数
     *
     * @param pageInfo 页面信息
     * @return ListData
     * @author : Yvon / 2021-09-03
     */
    public static ListData of(Page pageInfo) {
        ListData result = new ListData();

        result.setPage(pageInfo.getNumber());
        result.setSize(pageInfo.getSize());
        result.setTotalPages(pageInfo.getTotalPages());
        result.setTotalElements(pageInfo.getTotalElements());
        result.setFirst(pageInfo.isFirst());
        result.setLast(pageInfo.isLast());
        result.setHasNext(pageInfo.hasNext());
        result.setHasPrevious(pageInfo.hasPrevious());
        return result;
    }

    /**
     * 包装Mybatis-Plus分页参数
     *
     * @param pageInfo 页面信息
     * @return PageData
     * @author : Yvon / 2021-09-03
     */
    public static ListData of(IPage pageInfo) {
        ListData result = new ListData();

        result.setPage(pageInfo.getCurrent());
        result.setSize(pageInfo.getSize());
        result.setTotalPages(pageInfo.getPages());
        result.setTotalElements(pageInfo.getTotal());
        result.setFirst(1L == pageInfo.getCurrent());
        result.setLast(pageInfo.getCurrent() == pageInfo.getPages());
        result.setHasNext(pageInfo.getCurrent() < pageInfo.getPages());
        result.setHasPrevious(1L != pageInfo.getCurrent());
        return result;
    }

    /**
     * 构建分页(SpringData)
     *
     * @param pageInfo    SpringData分页
     * @param targetClass 目标类
     * @return ListData<D>
     * @author : Yvon / 2021-09-03
     */
    public static <E, D> ListData<D> restPage(Page<E> pageInfo, Class<D> targetClass)  {
        List<E> list = pageInfo.getContent();
        List<D> dtoList = copy(list, targetClass);
        ListData<D> listData = of(pageInfo);
        listData.setList(dtoList);
        return listData;
    }


    /**
     * 构建分页(Mybatis-Plus)
     *
     * @param pageInfo    Mybatis-Plus分页
     * @param targetClass 目标类
     * @return ListData<D>
     * @author : Yvon / 2021-09-03
     */
    public static <E, D> ListData<D> restPage(IPage<E> pageInfo, Class<D> targetClass)  {
        List<E> list = pageInfo.getRecords();
        List<D> dtoList = copy(list, targetClass);
        ListData<D> listData = of(pageInfo);
        listData.setList(dtoList);
        return listData;
    }

    /**
     * 构建分页(SpringData)
     *
     * @param pageInfo SpringData分页
     * @return ListData<V>
     * @author : Yvon / 2021-09-03
     */
    public static <V> ListData<V> restPage(Page<V> pageInfo)  {
        List<V> list = pageInfo.getContent();
        ListData<V> listData = of(pageInfo);
        listData.setList(list);
        return listData;
    }


    /**
     * 构建分页(Mybatis-Plus)
     *
     * @param pageInfo Mybatis-Plus分页
     * @return PageData<V>
     * @author : Yvon / 2021-09-03
     */
    public static <V> ListData<V> restPage(IPage<V> pageInfo)  {
        List<V> list = pageInfo.getRecords();
        ListData<V> listData = of(pageInfo);
        listData.setList(list);
        return listData;
    }

    /**
     * 构建分页(SpringData)
     *
     * @param pageInfo SpringData分页
     * @param list     列表
     * @return PageData<V>
     * @author : Yvon / 2021-09-03
     */
    public static <V> ListData<V> restPage(Page pageInfo, List<V> list)  {
        ListData<V> listData = of(pageInfo);
        listData.setList(list);
        return listData;
    }

    /**
     * 构建分页(Mybatis-Plus)
     *
     * @param pageInfo Mybatis-Plus分页
     * @param list     列表
     * @return PageData<V>
     * @author : Yvon / 2021-09-03
     */
    public static <V> ListData<V> restPage(IPage pageInfo, List<V> list)  {
        ListData<V> listData = of(pageInfo);
        listData.setList(list);
        return listData;
    }


    private static <T, S> List<T> copy(Collection<S> sources, Class<T> targetClass){
        if (CollectionUtils.isNotEmpty(sources)){
            return sources.stream()
                    .map(source -> BeanUtil.toBean(source, targetClass))
                    .collect(Collectors.toList());
        }
        return new ArrayList<>();
    }
}
